﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Management.Instrumentation;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using Microsoft.VisualBasic.Devices;

namespace SysMonitor
{
    [SuppressUnmanagedCodeSecurityAttribute]
    internal static class SafeNativeMethods
    {
        [DllImport("kernel32.dll",SetLastError=true, CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern bool GetSystemTimes(out TimeSpan lpIdleTime, out TimeSpan lpKernelTime, out TimeSpan lpUserTime);
    }

    public class Monitor
    {
        #region Attributes

        private static List<string> item = null;

        #endregion

        public static List<string> Start()
        {
            item = new List<string>();
            item.Add(DateTime.Now.ToString("HH:mm:ss"));
            if (GlobalAtrrib.myInfo.Disk) getDiskCount();
            if (GlobalAtrrib.myInfo.Memory) getMemoryCount();
            if (GlobalAtrrib.myInfo.CPU) getCPUCount();
            return item;
        }

        #region GetCount

        private static void getCPUCount()
        {
            int percent = 0;
            try
            {
                bool res = false;

                Processar PreProcessar = new Processar();
                Processar Processar = new Processar();
                res = SafeNativeMethods.GetSystemTimes(out PreProcessar.idleTime, out PreProcessar.kernelTime, out PreProcessar.userTime);
                Thread.Sleep(500);
                res = SafeNativeMethods.GetSystemTimes(out Processar.idleTime, out Processar.kernelTime, out Processar.userTime);
                Int64 idle = Processar.idleTime.Subtract(PreProcessar.idleTime).Ticks;
                Int64 kernel = Processar.kernelTime.Subtract(PreProcessar.kernelTime).Ticks;
                Int64 user = Processar.userTime.Subtract(PreProcessar.userTime).Ticks;

                Int64 cpu = (kernel + user - idle) * 100 / (kernel + user);
                percent = (int)cpu;
            }
            catch
            {
                ManagementClass cimobject = null;
                ManagementObjectCollection moc = null;
                try
                {
                    cimobject = new ManagementClass("Win32_Processor");
                    moc = cimobject.GetInstances();
                    foreach (ManagementObject mo in moc)
                    {
                        percent += (int.Parse(mo.Properties["LoadPercentage"].Value.ToString()));
                    }
                    percent /= moc.Count;
                }
                catch
                {
                    PerformanceCounter myPerf = null;
                    try
                    {
                        myPerf = new PerformanceCounter("Processor", "% Processor Time", "_Total");
                        myPerf.NextValue();
                        percent = (int)myPerf.NextValue();
                    }
                    catch
                    {
                    }
                    finally
                    {
                        myPerf.Dispose();
                    }
                }
                finally
                {
                    moc = null;
                    cimobject.Dispose();
                }
            }
            finally
            {
            }
            item.Add(percent.ToString() + "%");
        }

        private static void getMemoryCount()
        {
            ComputerInfo mycomInfo = null;
            ulong total = 0;
            ulong free = 0;
            try
            {
                mycomInfo = new ComputerInfo();
                total = mycomInfo.TotalPhysicalMemory / 1024 / 1024;
                free = mycomInfo.AvailablePhysicalMemory / 1024 / 1024;
            }
            catch
            {
                ManagementClass cimobject = null;
                ManagementObjectCollection moc = null;
                try
                {
                    cimobject = new ManagementClass("Win32_OperatingSystem");
                    moc = cimobject.GetInstances();
                    foreach (ManagementObject mo in moc)
                    {
                        total += ((ulong.Parse(mo.Properties["TotalVisibleMemorySize"].Value.ToString())) / 1024);
                        free += ((ulong.Parse(mo.Properties["FreePhysicalMemory"].Value.ToString())) / 1024);
                    }
                }
                catch
                {
                    PerformanceCounter myPerf = null;
                    try
                    {
                        myPerf = new PerformanceCounter("Memory", "Available MBytes");
                        myPerf.NextValue();
                        total = 0;
                        free = (ulong)myPerf.NextValue();
                    }
                    catch
                    {
                    }
                    finally
                    {
                        myPerf.Dispose();
                    }
                }
                finally
                {
                    moc = null;
                    cimobject.Dispose();
                }
            }

            item.Add(free.ToString() + "/" + total.ToString());
        }

        private static long GetTotalMemory()
        {
            //获取总物理内存大小
            long capacity = 0;
            ManagementClass cimobject = null;
            ManagementObjectCollection moc = null;
            try
            {
                cimobject = new ManagementClass("Win32_ComputerSystem");
                moc = cimobject.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    capacity += ((Int64.Parse(mo.Properties["TotalPhysicalMemory"].Value.ToString())));
                }
            }
            finally
            {
                moc = null;
                cimobject.Dispose();
            }
            return capacity / 1024 / 1024;
        }

        private static long GetFreeMemory()
        {
            //获取内存可用大小
            long available = 0;
            ManagementClass cimobject = null;
            ManagementObjectCollection moc = null;
            try
            {
                cimobject = new ManagementClass("Win32_PerfFormattedData_PerfOS_Memory");
                moc = cimobject.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    available += ((Int64.Parse(mo.Properties["AvailableMBytes"].Value.ToString())));

                }
            }
            finally
            {
                moc = null;
                cimobject.Dispose();
            }
            return available;
        }

        private static void getDiskCount()
        {
            List<string> mydisk = new List<string>();
            try
            {
                DriveInfo[] mydrivers = DriveInfo.GetDrives();
                foreach (DriveInfo mydriver in mydrivers)
                {
                    if (mydriver.DriveType == DriveType.Fixed) mydisk.Add(Math.Round(((decimal)mydriver.TotalFreeSpace / 1024 / 1024 / 1024), 2).ToString() + "/" + Math.Round(((decimal)mydriver.TotalSize / 1024 / 1024 / 1024), 2).ToString());
                }
            }
            catch
            {
                mydisk = new List<string>();
                ManagementClass cimobject = null;
                ManagementObjectCollection moc = null;
                try
                {
                    cimobject = new ManagementClass("Win32_LogicalDisk");
                    moc = cimobject.GetInstances();
                    foreach (ManagementObject mo in moc)
                    {
                        if (int.Parse(mo.Properties["DriveType"].Value.ToString()) == 3) mydisk.Add(Math.Round((decimal.Parse(mo.Properties["FreeSpace"].Value.ToString()) / 1024 / 1024 / 1024), 2).ToString() + "/" + Math.Round((decimal.Parse(mo.Properties["Size"].Value.ToString()) / 1024 / 1024 / 1024), 2).ToString());

                    }
                }
                catch
                {
                    mydisk = new List<string>();
                    PerformanceCounterCategory category = null;
                    PerformanceCounter myPerf = null;
                    try
                    {
                        category = new PerformanceCounterCategory("LogicalDisk");
                        foreach (string name in category.GetInstanceNames())
                        {
                            // This one exists on every computer.  
                            if (name == "_Total") continue;
                            myPerf = new PerformanceCounter("LogicalDisk", "Free Megabytes", name);
                            myPerf.NextValue();
                            mydisk.Add(Math.Round(myPerf.NextValue() / 1024, 2).ToString());
                        }
                    }
                    catch
                    {
                    }
                    finally
                    {
                        myPerf.Dispose();
                    }
                }
                finally
                {
                    moc = null;
                    cimobject.Dispose();
                }
            }
            foreach (string disk in mydisk) item.Add(disk);
        }

        #endregion
    }

    public struct SysInfo
    {
        public bool Disk;
        public bool Memory;
        public bool CPU;
    }

    public struct Processar
    {
        public TimeSpan idleTime;
        public TimeSpan kernelTime;
        public TimeSpan userTime;
    }
}
